home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xearth-0.92 / render.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  10KB  |  487 lines

  1. /*
  2.  * render.c
  3.  * kirk johnson
  4.  * october 1993
  5.  *
  6.  * RCS $Id: render.c,v 1.7 1994/05/23 23:03:01 tuna Exp $
  7.  *
  8.  * Copyright (C) 1989, 1990, 1993, 1994 Kirk Lauritz Johnson
  9.  *
  10.  * Parts of the source code (as marked) are:
  11.  *   Copyright (C) 1989, 1990, 1991 by Jim Frost
  12.  *   Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com>
  13.  *
  14.  * Permission to use, copy, modify, distribute, and sell this
  15.  * software and its documentation for any purpose is hereby granted
  16.  * without fee, provided that the above copyright notice appear in
  17.  * all copies and that both that copyright notice and this
  18.  * permission notice appear in supporting documentation. The author
  19.  * makes no representations about the suitability of this software
  20.  * for any purpose. It is provided "as is" without express or
  21.  * implied warranty.
  22.  *
  23.  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  24.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  25.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
  26.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  27.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  28.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  29.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  30.  */
  31.  
  32. #include "xearth.h"
  33. #include "kljcpyrt.h"
  34.  
  35. static void new_stars();
  36. static void new_grid();
  37.  
  38. static int      scanbitcnt;
  39. static ScanBit *scanbit;
  40. static u_char   scan_to_pix[256];
  41.  
  42. static ExtArr   dots = NULL;
  43. static int      dotcnt;
  44. static ScanDot *dot;
  45.  
  46.  
  47. static int dot_comp(a, b)
  48.      void *a;
  49.      void *b;
  50. {
  51.   return (((ScanDot *) a)->y - ((ScanDot *) b)->y);
  52. }
  53.  
  54.  
  55. static void render_rows_setup()
  56. {
  57.   int i;
  58.  
  59.   scanbitcnt = scanbits->count;
  60.   scanbit    = (ScanBit *) scanbits->body;
  61.   dotcnt     = dots->count;
  62.   dot        = (ScanDot *) dots->body;
  63.  
  64.   /* precompute table for translating between
  65.    * scan buffer values and pixel types
  66.    */
  67.   for (i=0; i<256; i++)
  68.     if (i == 0)
  69.       scan_to_pix[i] = PixTypeSpace;
  70.     else if (i > 64)
  71.       scan_to_pix[i] = PixTypeLand;
  72.     else
  73.       scan_to_pix[i] = PixTypeWater;
  74. }
  75.  
  76.  
  77. static void render_next_row(buf, idx)
  78.      char *buf;
  79.      int   idx;
  80. {
  81.   int      i, i_lim;
  82.   int      tmp;
  83.   int      _scanbitcnt;
  84.   ScanBit *_scanbit;
  85.  
  86.   xearth_bzero((char *) buf, wdth);
  87.  
  88.   /* explicitly copy scanbitcnt and scanbit to local variables
  89.    * to help compilers figure out that they can be registered
  90.    */
  91.   _scanbitcnt = scanbitcnt;
  92.   _scanbit    = scanbit;
  93.  
  94.   while ((_scanbitcnt > 0) && (_scanbit->y == idx))
  95.   {
  96.     /* use i_lim to encourage compilers to register loop limit
  97.      */
  98.     i_lim = _scanbit->hi_x;
  99.     for (i=_scanbit->lo_x; i<=i_lim; i++)
  100.       buf[i] += _scanbit->val;
  101.  
  102.     _scanbit    += 1;
  103.     _scanbitcnt -= 1;
  104.   }
  105.  
  106.   /* copy changes to scanbitcnt and scanbit out to memory
  107.    */
  108.   scanbitcnt = _scanbitcnt;
  109.   scanbit    = _scanbit;
  110.  
  111.   /* use i_lim to encourage compilers to register loop limit
  112.    */
  113.   i_lim = wdth;
  114.   for (i=0; i<i_lim; i++)
  115.     buf[i] = scan_to_pix[(u_char) buf[i]];
  116.  
  117.   while ((dotcnt > 0) && (dot->y == idx))
  118.   {
  119.     tmp = dot->x;
  120.  
  121.     if (dot->type == DotTypeStar)
  122.     {
  123.       if (buf[tmp] == PixTypeSpace)
  124.     buf[tmp] = PixTypeStar;
  125.     }
  126.     else
  127.     {
  128.       switch (buf[tmp])
  129.       {
  130.       case PixTypeLand:
  131.     buf[tmp] = PixTypeGridLand;
  132.     break;
  133.  
  134.       case PixTypeWater:
  135.     buf[tmp] = PixTypeGridWater;
  136.     break;
  137.       }
  138.     }
  139.  
  140.     dot    += 1;
  141.     dotcnt -= 1;
  142.   }
  143. }
  144.  
  145.  
  146. void render_no_shading(rowfunc)
  147.      void (*rowfunc)();
  148. {
  149.   int     i, i_lim;
  150.   int     j, j_lim;
  151.   char   *scanbuf;
  152.   u_char *row;
  153.   u_char *tmp;
  154.  
  155.   scanbuf = (char *) malloc((unsigned) wdth);
  156.   assert(scanbuf != NULL);
  157.   row = (u_char *) malloc((unsigned) wdth*3);
  158.   assert(row != NULL);
  159.   render_rows_setup();
  160.  
  161.   /* main render loop
  162.    * (use i_lim and j_lim to encourage compilers to register loop limits)
  163.    */
  164.   i_lim = hght;
  165.   j_lim = wdth;
  166.   for (i=0; i<i_lim; i++)
  167.   {
  168.     render_next_row(scanbuf, i);
  169.  
  170.     tmp = row;
  171.     for (j=0; j<j_lim; j++)
  172.     {
  173.       switch (scanbuf[j])
  174.       {
  175.       case PixTypeSpace:    /* black */
  176.     tmp[0] = 0;
  177.     tmp[1] = 0;
  178.     tmp[2] = 0;
  179.     break;
  180.  
  181.       case PixTypeStar:        /* white */
  182.       case PixTypeGridLand:
  183.       case PixTypeGridWater:
  184.         tmp[0] = 255;
  185.         tmp[1] = 255;
  186.         tmp[2] = 255;
  187.     break;
  188.  
  189.       case PixTypeLand:        /* green */
  190.         tmp[0] = 0;
  191.         tmp[1] = 255;
  192.         tmp[2] = 0;
  193.     break;
  194.  
  195.       case PixTypeWater:    /* blue */
  196.         tmp[0] = 0;
  197.         tmp[1] = 0;
  198.         tmp[2] = 255;
  199.     break;
  200.  
  201.       default:
  202.     assert(0);
  203.       }
  204.  
  205.       tmp += 3;
  206.     }
  207.  
  208.     rowfunc(row);
  209.   }
  210.  
  211.   free(scanbuf);
  212.   free(row);
  213. }
  214.  
  215.  
  216. void render_with_shading(rowfunc)
  217.      void (*rowfunc)();
  218. {
  219.   int     i, i_lim;
  220.   int     j, j_lim;
  221.   int     base_val;
  222.   double  delta_val;
  223.   int     val;
  224.   char   *scanbuf;
  225.   u_char *row;
  226.   u_char *tmp;
  227.   double  tmp1, tmp2;
  228.   double  x, y, z;
  229.   double  sol[3];
  230.   double  scale;
  231.   double *inv_x;
  232.  
  233.   scanbuf = (char *) malloc((unsigned) wdth);
  234.   assert(scanbuf != NULL);
  235.   row = (u_char *) malloc((unsigned) wdth*3);
  236.   assert(row != NULL);
  237.   render_rows_setup();
  238.  
  239.   sol[0] = sin(sun_lon * (M_PI/180)) * cos(sun_lat * (M_PI/180));
  240.   sol[1] = sin(sun_lat * (M_PI/180));
  241.   sol[2] = cos(sun_lon * (M_PI/180)) * cos(sun_lat * (M_PI/180));
  242.  
  243.   tmp1 = (cos_view_lon * sol[0]) - (sin_view_lon * sol[2]);
  244.   tmp2 = (sin_view_lon * sol[0]) + (cos_view_lon * sol[2]);
  245.   sol[0] = tmp1;
  246.   sol[2] = tmp2;
  247.  
  248.   tmp1 = (cos_view_lat * sol[1]) - (sin_view_lat * sol[2]);
  249.   tmp2 = (sin_view_lat * sol[1]) + (cos_view_lat * sol[2]);
  250.   sol[1] = tmp1;
  251.   sol[2] = tmp2;
  252.  
  253.   /* precompute INV_XPROJECT() values
  254.    * (use i_lim to encourage compilers to register loop limit)
  255.    */
  256.   inv_x = (double *) malloc((unsigned) sizeof(double) * wdth);
  257.   assert(inv_x != NULL);
  258.   i_lim = wdth;
  259.   for (i=0; i<i_lim; i++)
  260.     inv_x[i] = INV_XPROJECT(i);
  261.  
  262.   /* precompute shading parameters */
  263.   base_val  = (night * 255.99) / 100;
  264.   delta_val = (day * 255.99) / 100 - base_val;
  265.  
  266.   /* main render loop
  267.    * (use i_lim and j_lim to encourage compilers to register loop limits)
  268.    */
  269.   i_lim = hght;
  270.   j_lim = wdth;
  271.   for (i=0; i<i_lim; i++)
  272.   {
  273.     y = INV_YPROJECT(i);
  274.     render_next_row(scanbuf, i);
  275.  
  276.     tmp = row;
  277.     for (j=0; j<j_lim; j++)
  278.     {
  279.       switch (scanbuf[j])
  280.       {
  281.       case PixTypeSpace:    /* black */
  282.     tmp[0] = 0;
  283.     tmp[1] = 0;
  284.     tmp[2] = 0;
  285.     break;
  286.  
  287.       case PixTypeStar:        /* white */
  288.       case PixTypeGridLand:
  289.       case PixTypeGridWater:
  290.         tmp[0] = 255;
  291.         tmp[1] = 255;
  292.         tmp[2] = 255;
  293.     break;
  294.  
  295.       case PixTypeLand:        /* green */
  296.       case PixTypeWater:
  297.         x = inv_x[j];
  298.         z = 1 - x*x - y*y;
  299.         z = SQRT(z);
  300.         scale = x*sol[0] + y*sol[1] + z*sol[2];
  301.         if (scale < 0)
  302.         {
  303.           val = base_val;
  304.         }
  305.         else
  306.         {
  307.       val = base_val + scale*delta_val;
  308.       if (val > 255) val = 255;
  309.         }
  310.         assert(val >= 0);
  311.  
  312.         if (scanbuf[j] == 1)
  313.         {
  314.           /* land (green) */
  315.           tmp[0] = 0;
  316.           tmp[1] = val;
  317.           tmp[2] = 0;
  318.         }
  319.         else
  320.         {
  321.           /* water (blue) */
  322.           tmp[0] = 0;
  323.           tmp[1] = 0;
  324.           tmp[2] = val;
  325.         }
  326.     break;
  327.  
  328.       default:
  329.     assert(0);
  330.       }
  331.  
  332.       tmp += 3;
  333.     }
  334.  
  335.     rowfunc(row);
  336.   }
  337.  
  338.   free(scanbuf);
  339.   free(row);
  340.   free(inv_x);
  341. }
  342.  
  343.  
  344. void do_dots()
  345. {
  346.   if (dots == NULL)
  347.     dots = extarr_alloc(sizeof(ScanDot));
  348.   else
  349.     dots->count = 0;
  350.  
  351.   if (do_stars) new_stars(star_freq);
  352.   if (do_grid) new_grid(grid_big, grid_small);
  353.  
  354.   qsort(dots->body, dots->count, sizeof(ScanDot), dot_comp);
  355. }
  356.  
  357.  
  358. static void new_stars(freq)
  359.      double freq;
  360. {
  361.   int      i;
  362.   int      x, y;
  363.   int      max_stars;
  364.   ScanDot *newdot;
  365.  
  366.   max_stars = wdth * hght * freq;
  367.  
  368.   for (i=0; i<max_stars; i++)
  369.   {
  370.     x = random() % wdth;
  371.     y = random() % hght;
  372.  
  373.     newdot = (ScanDot *) extarr_next(dots);
  374.     newdot->x    = x;
  375.     newdot->y    = y;
  376.     newdot->type = DotTypeStar;
  377.   }
  378. }
  379.  
  380.  
  381. static void new_grid(big, small)
  382.      int big;
  383.      int small;
  384. {
  385.   int      i, j;
  386.   int      x, y;
  387.   int      cnt;
  388.   double   lat, lon;
  389.   double   lat_scale, lon_scale;
  390.   double   cos_lat, sin_lat;
  391.   double   cos_lon, sin_lon;
  392.   double   pos[3];
  393.   double   tmp1, tmp2;
  394.   ScanDot *newdot;
  395.  
  396.   /* lines of longitude
  397.    */
  398.   lon_scale = M_PI / (2 * big);
  399.   lat_scale = M_PI / (2 * big * small);
  400.   for (i=(-2*big); i<(2*big); i++)
  401.   {
  402.     lon     = i * lon_scale;
  403.     cos_lon = cos(lon);
  404.     sin_lon = sin(lon);
  405.  
  406.     for (j=(-(big*small)+1); j<(big*small); j++)
  407.     {
  408.       lat     = j * lat_scale;
  409.       cos_lat = cos(lat);
  410.       sin_lat = sin(lat);
  411.  
  412.       pos[0] = sin_lon * cos_lat;
  413.       pos[1] = sin_lat;
  414.       pos[2] = cos_lon * cos_lat;
  415.  
  416.       tmp1 = (cos_view_lon * pos[0]) - (sin_view_lon * pos[2]);
  417.       tmp2 = (sin_view_lon * pos[0]) + (cos_view_lon * pos[2]);
  418.       pos[0] = tmp1;
  419.       pos[2] = tmp2;
  420.  
  421.       tmp1 = (cos_view_lat * pos[1]) - (sin_view_lat * pos[2]);
  422.       tmp2 = (sin_view_lat * pos[1]) + (cos_view_lat * pos[2]);
  423.       pos[1] = tmp1;
  424.       pos[2] = tmp2;
  425.  
  426.       if (pos[2] >= 0)
  427.       {
  428.     x = XPROJECT(pos[0]);
  429.     y = YPROJECT(pos[1]);
  430.     if ((x >= 0) && (x < wdth) && (y >= 0) && (y < hght))
  431.     {
  432.       newdot = (ScanDot *) extarr_next(dots);
  433.       newdot->x    = x;
  434.       newdot->y    = y;
  435.       newdot->type = DotTypeGrid;
  436.     }
  437.       }
  438.     }
  439.   }
  440.  
  441.   /* lines of latitude
  442.    */
  443.   lat_scale = M_PI / (2 * big);
  444.   for (i=(1-big); i<big; i++)
  445.   {
  446.     lat       = i * lat_scale;
  447.     cos_lat   = cos(lat);
  448.     sin_lat   = sin(lat);
  449.     cnt       = 2 * ((int) ((cos_lat * small) + 0.5)) * big;
  450.     lon_scale = M_PI / cnt;
  451.  
  452.     for (j=(-cnt); j<cnt; j++)
  453.     {
  454.       lon     = j * lon_scale;
  455.       cos_lon = cos(lon);
  456.       sin_lon = sin(lon);
  457.  
  458.       pos[0] = sin_lon * cos_lat;
  459.       pos[1] = sin_lat;
  460.       pos[2] = cos_lon * cos_lat;
  461.  
  462.       tmp1 = (cos_view_lon * pos[0]) - (sin_view_lon * pos[2]);
  463.       tmp2 = (sin_view_lon * pos[0]) + (cos_view_lon * pos[2]);
  464.       pos[0] = tmp1;
  465.       pos[2] = tmp2;
  466.  
  467.       tmp1 = (cos_view_lat * pos[1]) - (sin_view_lat * pos[2]);
  468.       tmp2 = (sin_view_lat * pos[1]) + (cos_view_lat * pos[2]);
  469.       pos[1] = tmp1;
  470.       pos[2] = tmp2;
  471.  
  472.       if (pos[2] >= 0)
  473.       {
  474.     x = XPROJECT(pos[0]);
  475.     y = YPROJECT(pos[1]);
  476.     if ((x >= 0) && (x < wdth) && (y >= 0) && (y < hght))
  477.     {
  478.       newdot = (ScanDot *) extarr_next(dots);
  479.       newdot->x    = x;
  480.       newdot->y    = y;
  481.       newdot->type = DotTypeGrid;
  482.     }
  483.       }
  484.     }
  485.   }
  486. }
  487.